import com.svcon.jdbf.DBFReader;
import com.svcon.jdbf.JDBFException;
import junitx.framework.Assert;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class DBFFileAssert {

    private DBFFileAssert() {
    }

    public static void assertEquals(
            File expected, File actual, int[] fieldToCheckPositions
    ) throws JDBFException, FileNotFoundException {
        assertEquals(
                "Comparing " + expected + " and " + actual + ", ",
                new DBFReader(new FileInputStream(expected)),
                new DBFReader(new FileInputStream(actual)),
                fieldToCheckPositions
        );
    }

    public static void assertEquals(
            DBFReader expected, DBFReader actual, int[] fieldToCheckPositions
    ) throws JDBFException {
        assertEquals(null, expected, actual, fieldToCheckPositions);
    }

    public static void assertEquals(
            String message,
            DBFReader expected, DBFReader actual,
            int[] fieldToCheckPositions
    ) throws JDBFException {
        String formatted;

        Assert.assertNotNull(message, expected);
        Assert.assertNotNull(message, actual);

        formatted = "";
        if (message != null) {
            formatted = message + " ";
        }

        for (int i : fieldToCheckPositions) {
            Assert.assertEquals(formatted + " [" + i + "] field name ", actual.getField(i).getName(), expected.getField(i).getName());
            Assert.assertEquals(formatted + " [" + i + "] field type", actual.getField(i).getType(), expected.getField(i).getType());
        }

        int lineNumber = 0;
        while (actual.hasNextRecord() || expected.hasNextRecord()) {
            if (expected.hasNextRecord()) {
                Object[] expRow = expected.nextRecord();

                if (actual.hasNextRecord()) {
                    assertRow(formatted + "Line [" + lineNumber + "], ", expRow, actual.nextRecord(), actual, fieldToCheckPositions);
                } else {
                    Assert.fail(formatted + "Line [" + lineNumber + "] expected <" + expRow + "> but was <EOF>");
                }
            } else {
                if (actual.hasNextRecord()) {
                    Object[] actRow = actual.nextRecord();

                    Assert.fail(formatted + "Line [" + lineNumber + "] expected <EOF> but was <" + actRow + ">");
                }
            }

            lineNumber++;
        }
    }

    private static void assertRow(String s,
                                  Object[] expRow, Object[] actRow, DBFReader reader,
                                  int[] fieldToCheckPositions
    ) {
        for (int position : fieldToCheckPositions) {
            Assert.assertEquals(s + reader.getField(position).getName() + " (" + position + ") field", expRow[position], actRow[position]);
        }
    }
}